﻿using UnityEngine;
using System;
using System.IO;
using System.Text;
using System.Collections;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
using UObject = UnityEngine.Object;
#if UNITY_EDITOR
using UnityEditor;
#endif

public class MainUtil
{
    private static List<string> luaPaths = new List<string>();

    public static int Int(object o) {
        return Convert.ToInt32(o);
    }

    public static float Float(object o) {
        return (float)Math.Round(Convert.ToSingle(o), 2);
    }

    public static long Long(object o) {
        return Convert.ToInt64(o);
    }

    public static int Random(int min, int max) {
        return UnityEngine.Random.Range(min, max);
    }

    public static float Random(float min, float max) {
        return UnityEngine.Random.Range(min, max);
    }

    public static string Uid(string uid) {
        int position = uid.LastIndexOf('_');
        return uid.Remove(0, position + 1);
    }

    public static long GetTime() {
        TimeSpan ts = new TimeSpan(DateTime.UtcNow.Ticks - new DateTime(1970, 1, 1, 0, 0, 0).Ticks);
        return (long)ts.TotalMilliseconds;
    }

    /// <summary>
    /// 搜索子物体组件-GameObject版
    /// </summary>
    public static T Get<T>(GameObject go, string subnode) where T : Component {
        if (go != null) {
            Transform sub = go.transform.Find(subnode);
            if (sub != null) return sub.GetComponent<T>();
        }
        return null;
    }

    /// <summary>
    /// 搜索子物体组件-Transform版
    /// </summary>
    public static T Get<T>(Transform go, string subnode) where T : Component {
        if (go != null) {
            Transform sub = go.Find(subnode);
            if (sub != null) return sub.GetComponent<T>();
        }
        return null;
    }

    /// <summary>
    /// 搜索子物体组件-Component版
    /// </summary>
    public static T Get<T>(Component go, string subnode) where T : Component {
        return go.transform.Find(subnode).GetComponent<T>();
    }

    /// <summary>
    /// 添加组件
    /// </summary>
    public static T Add<T>(GameObject go) where T : Component {
        if (go != null) {
            T[] ts = go.GetComponents<T>();
            for (int i = 0; i < ts.Length; i++) {
                if (ts[i] != null) GameObject.Destroy(ts[i]);
            }
            return go.gameObject.AddComponent<T>();
        }
        return null;
    }

    /// <summary>
    /// 添加组件
    /// </summary>
    public static T Add<T>(Transform go) where T : Component {
        return Add<T>(go.gameObject);
    }

    /// <summary>
    /// 查找子对象
    /// </summary>
    public static GameObject Child(GameObject go, string subnode) {
        return Child(go.transform, subnode);
    }

    /// <summary>
    /// 查找子对象
    /// </summary>
    public static GameObject Child(Transform go, string subnode) {
        Transform tran = go.Find(subnode);
        if (tran == null) return null;
        return tran.gameObject;
    }

    /// <summary>
    /// 取平级对象
    /// </summary>
    public static GameObject Peer(GameObject go, string subnode) {
        return Peer(go.transform, subnode);
    }

    /// <summary>
    /// 取平级对象
    /// </summary>
    public static GameObject Peer(Transform go, string subnode) {
        Transform tran = go.parent.Find(subnode);
        if (tran == null) return null;
        return tran.gameObject;
    }

    /// <summary>
    /// 计算字符串的MD5值
    /// </summary>
    public static string md5(string source) {
        MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
        byte[] data = System.Text.Encoding.UTF8.GetBytes(source);
        byte[] md5Data = md5.ComputeHash(data, 0, data.Length);
        md5.Clear();

        string destString = "";
        for (int i = 0; i < md5Data.Length; i++) {
            destString += System.Convert.ToString(md5Data[i], 16).PadLeft(2, '0');
        }
        destString = destString.PadLeft(32, '0');
        return destString;
    }

//	/// <summary>
//	/// 字符串加密
//	/// </summary>
//	/// <returns>The M d5 string.</returns>
//	/// <param name="str">String.</param>
//	public string GetMD5String(string str)
//	{
//		MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
//		//md5 = new MD5CryptoServiceProvider();
//		byte[] data = System.Text.Encoding.Default.GetBytes(str);// 返回结果:一个字节数组，包含对指定的字符集进行编码的结果。
//		byte[] md5data = md5.ComputeHash(data);//计算指定字节数组的哈希值。
//		//md5.Clear();
//		StringBuilder builder = new StringBuilder();
//		for (int i = 0; i < md5data.Length; i++)
//		{
//			//Console.WriteLine(md5data[i].ToString());
//			builder.Append(md5data[i].ToString("X2"));
//		}
//		//返回加密后的字符串
//		return builder.ToString();
//	}


    /// <summary>
    /// 计算文件的MD5值
    /// </summary>
    public static string md5file(string file) {
        try {
            FileStream fs = new FileStream(file, FileMode.Open);
            System.Security.Cryptography.MD5 md5 = new System.Security.Cryptography.MD5CryptoServiceProvider();
            byte[] retVal = md5.ComputeHash(fs);
            fs.Close();

            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < retVal.Length; i++) {
                sb.Append(retVal[i].ToString("x2"));
            }
            return sb.ToString();
        } catch (Exception ex) {
            throw new Exception("md5file() fail, error:" + ex.Message);
        }
    }

//	/// <summary>
//	/// 文件加密
//	/// </summary>
//	/// <returns>The file md5.</returns>
//	/// <param name="path">Path.</param>
//	public  string GetFileMd5(string path)
//	{
//		string ctyptStr = "";
//		byte[] cryptBytes;
//		using (FileStream fs = new FileStream(path,FileMode.Open))//选择文件
//		{
//			MD5CryptoServiceProvider md5 = new MD5CryptoServiceProvider();
//			cryptBytes = md5.ComputeHash(fs);
//		}
//		for (int i = 0; i < cryptBytes.Length; i++)
//		{
//			ctyptStr += cryptBytes[i].ToString("X2");
//		}
//		return ctyptStr;
//	}


    /// <summary>
    /// 清除所有子节点
    /// </summary>
    public static void ClearChild(Transform go) {
        if (go == null) return;
        for (int i = go.childCount - 1; i >= 0; i--) {
            GameObject.Destroy(go.GetChild(i).gameObject);
        }
    }

    /// <summary>
    /// 清理内存
    /// </summary>
    public static void ClearMemory() {
        Resources.UnloadUnusedAssets();
        GC.Collect(); 
        //LuaManager mgr = AppFacade.Instance.GetManager<LuaManager>(ManagerName.Lua);
        //if (mgr != null) mgr.LuaGC();
    }


    public static string GetRelativePath() {
        //if (Application.isEditor)
        //    return "file://" + System.Environment.CurrentDirectory.Replace("\\", "/") + "/Assets/" + AppConst.AssetDir + "/";
        //else if (Application.isMobilePlatform || Application.isConsolePlatform)
        //    return "file:///" + DataPath;
        //else // For standalone player.
        //    return "file://" + Application.streamingAssetsPath + "/";
        return "";
    }

    /// <summary>
    /// 取得行文本
    /// </summary>
    public static string GetFileText(string path) {
        return File.ReadAllText(path);
    }

    /// <summary>
    /// 网络可用
    /// </summary>
    public static bool NetAvailable {
        get {
            return Application.internetReachability != NetworkReachability.NotReachable;
        }
    }

    /// <summary>
    /// 是否是无线
    /// </summary>
    public static bool IsWifi {
        get {
            return Application.internetReachability == NetworkReachability.ReachableViaLocalAreaNetwork;
        }
    }


    public static void Log(object str) {
        if (MainFacade.Instance.TipMgr != null) {
            MainFacade.Instance.TipMgr.SetTip(str.ToString());
        }
        Debug.Log(str);
    }

    public static void LogWarning(object str)
    {
        Debug.LogWarning(str);
    }

    public static void LogError(object str)
    {
        Debug.LogError(str);
    }

    /// <summary>
    /// 防止初学者不按步骤来操作
    /// </summary>
    /// <returns></returns>
    //public static int CheckRuntimeFile() {
    //    if (!Application.isEditor) return 0;
    //    string streamDir = Application.dataPath + "/StreamingAssets/";
    //    if (!Directory.Exists(streamDir)) {
    //        return -1;
    //    } else {
    //        string[] files = Directory.GetFiles(streamDir);
    //        if (files.Length == 0) return -1;

    //        if (!File.Exists(streamDir + "files.txt")) {
    //            return -1;
    //        }
    //    }
    //    string sourceDir = AppConst.FrameworkRoot + "/ToLua/Source/Generate/";
    //    if (!Directory.Exists(sourceDir)) {
    //        return -2;
    //    } else {
    //        string[] files = Directory.GetFiles(sourceDir);
    //        if (files.Length == 0) return -2;
    //    }
    //    return 0;
    //}

    /// <summary>
    /// 执行Lua方法
    /// </summary>
    //public static object[] CallMethod(string module, string func, params object[] args) {
    //    LuaManager luaMgr = AppFacade.Instance.GetManager<LuaManager>(ManagerName.Lua);
    //    if (luaMgr == null) return null;
    //    return luaMgr.CallFunction(module + "." + func, args);
    //}

            /// <summary>
    /// 检查运行环境
    /// </summary>
    public static bool CheckEnvironment() {
#if UNITY_EDITOR
        //int resultId = Util.CheckRuntimeFile();
        //if (resultId == -1) {
        //    Debug.LogError("没有找到框架所需要的资源，单击Game菜单下Build xxx Resource生成！！");
        //    EditorApplication.isPlaying = false;
        //    return false;
        //} else if (resultId == -2) {
        //    Debug.LogError("没有找到Wrap脚本缓存，单击Lua菜单下Gen Lua Wrap Files生成脚本！！");
        //    EditorApplication.isPlaying = false;
        //    return false;
        //}
        //if (Application.loadedLevelName == "Test" && !AppConst.DebugMode) {
        //    Debug.LogError("测试场景，必须打开调试模式，AppConst.DebugMode = true！！");
        //    EditorApplication.isPlaying = false;
        //    return false;
        //}
        return true;
#endif
        return true;
    }
}

/**
*Createed by yellowTT's game
*FileName:     MathUtil.cs
*Author:       yellowTT
*UnityVersion：2020.1.14f1c1
*Date:         2020年12月16日,星期三, 21时59分07秒
*/


namespace GameUtil
{
    public partial class AppUtil
    {
        private static float angle2Radian = Mathf.PI / 180; 
        private static float radian2Angle = 180 / Mathf.PI; 

        /// <summary>
        /// 构建一个绕世界坐标轴X旋转angle角度的矩阵，列矩阵
        /// </summary>
        /// <returns></returns>
        public static Matrix4x4 RotateAroundWorldXMatrix(float angle)
        {   
            //因为是通过旋转坐标轴来获得变换矩阵的，而坐标轴和物体的旋转方向应该是相反的
            angle = -angle;
            float radian = angle * angle2Radian;
            Matrix4x4 matrix = new Matrix4x4();
            matrix.SetRow(0,new Vector4(1,0,0,0));
            matrix.SetRow(1,new Vector4(0,Mathf.Cos(radian),Mathf.Sin(radian),0));
            matrix.SetRow(2,new Vector4(0,-Mathf.Sin(radian),Mathf.Cos(radian),0));
            matrix.SetRow(3,new Vector4(0,0,0,1));

            return matrix;
        }
        
        /// <summary>
        /// 构建一个绕世界坐标轴Y旋转angle角度的矩阵，列矩阵
        /// </summary>
        /// <returns></returns>
        public static Matrix4x4 RotateAroundWorldYMatrix(float angle)
        {
            angle = -angle;
            float radian = angle * angle2Radian;
            Matrix4x4 matrix = new Matrix4x4();
            matrix.SetRow(0,new Vector4(Mathf.Cos(radian),0,-Mathf.Sin(radian),0));
            matrix.SetRow(1,new Vector4(0,1,0,0));
            matrix.SetRow(2,new Vector4(Mathf.Sin(radian),0,Mathf.Cos(radian),0));
            matrix.SetRow(3,new Vector4(0,0,0,1));

            return matrix;
        }
        
        /// <summary>
        /// 构建一个绕世界坐标轴Z旋转angle角度的矩阵，列矩阵
        /// </summary>
        /// <returns></returns>
        public static Matrix4x4 RotateAroundWorldZMatrix(float angle)
        {
            angle = -angle;
            float radian = angle * angle2Radian;
            Matrix4x4 matrix = new Matrix4x4();
            matrix.SetRow(0,new Vector4(Mathf.Cos(radian),Mathf.Sin(radian),0,0));
            matrix.SetRow(1,new Vector4(-Mathf.Sin(radian),Mathf.Cos(radian),0,0));
            matrix.SetRow(2,new Vector4(0,0,1,0));
            matrix.SetRow(3,new Vector4(0,0,0,1));

            return matrix;
        }

        public static Vector3 Vector3Rotate(float angle,Vector3 axis)
        {
            return Vector3.one;
        }
    }
}

